import matplotlib
matplotlib.use('Agg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
import pylab as p
import time

import vtk
import wx
from vtk.wx.wxVTKRenderWindowInteractor import *

def create(parent, root):    
    return Plotter(parent, root)
    
class Plotter():
    def __init__(self, parent, root):
        self.parent = parent
        self._root = root        
        
        self.whichdata = 0
        self.filtervalues = []
        self.yValues1 = [0]
        self.lastclicktime = 0
        self.label = "Values-over-time plot, right-click to select parameter."
        self.plotcolor = (1.0, 1.0, 1.0)
        self.cursor = -1
     
        self.DefineLookupTable()
        self.SetupRenderWindow()
        #~ self.ShowPlot()
    
    def SetupRenderWindow(self):
        renwini4 = wxVTKRenderWindowInteractor(self.parent, -1)
        self.iren = renwini4
        self.renWin = renwini4.GetRenderWindow()
        self.iren.Unbind(wx.EVT_LEFT_DOWN)
        self.iren.Unbind(wx.EVT_RIGHT_DOWN)
        self.iren.Bind(wx.EVT_LEFT_DOWN, self.PlotSelected)
        self.iren.Bind(wx.EVT_RIGHT_DOWN, self.ShowMenu)
        
        self.ren = vtk.vtkRenderer()
        self.renWin.AddRenderer(self.ren)
        

        
    def ShowMenu(self, event):
        #~ x, y = self.iren.GetEventPosition()
        #add parameter menu
        
        jAngles = self.parent.parent.Filters.jointAngleCollection
        menu2 = wx.Menu()
        for i in jAngles:
            tmpid = wx.NewId()
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            menu2.Append(id = tmpid, text=verhaal)
            self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal, dataset=0: self.OnMenu(evt, temp, dataset), id = tmpid )
 
                    
        menu1 = wx.Menu()    
        menu1.AppendSubMenu(submenu=menu2, text='Dataset 1')
        if len(self.parent.parent.splineReferences) > 0:
            menu3 = wx.Menu()
            for i in jAngles:
                tmpid = wx.NewId()
                verhaal = i['description']
                verhaal = verhaal.replace('\n', ' ')
                menu3.Append(id = tmpid, text=verhaal)
                self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal, dataset=1: self.OnMenu(evt, temp, dataset), id = tmpid )                       
            menu1.AppendSubMenu(submenu=menu3, text='Dataset 2')
        
        menuMain = wx.Menu() 
        menuMain.AppendSubMenu(submenu=menu1, text='Change parameter')
        
        tmpid = wx.NewId()
        menuMain.Append(id = tmpid, text='Play Sequence')
        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp='Play Sequence', dataset=-1: self.OnMenu(evt, temp, dataset), id = tmpid )
        
        tmpid = wx.NewId()
        menuMain.Append(id = tmpid, text='Trace Sequence')
        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp='Trace Sequence', dataset=-1: self.OnMenu(evt, temp, dataset), id = tmpid )
        
        tmpid = wx.NewId()
        menuMain.Append(id = tmpid, text='Clear Filter')
        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp='Clear Filter', dataset=-1: self.OnMenu(evt, temp, dataset), id = tmpid )
        
        tmpid = wx.NewId()
        menuMain.Append(id = tmpid, text='Add Parameter Plot')
        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp='Add Parameter Plot', dataset=-1: self.OnMenu(evt, temp, dataset), id = tmpid )
        
        if len(self.parent.sequenceplotters)>1:
            tmpid = wx.NewId()
            menuMain.Append(id = tmpid, text='Remove Parameter Plot')
            self.parent.Bind(wx.EVT_MENU,  lambda evt, temp='Remove Parameter Plot', dataset=0: self.OnMenu(evt, temp, dataset), id = tmpid )
        
        mouseposition = wx.GetMousePosition()
        self.parent.PopupMenu( menuMain, (mouseposition[0], mouseposition[1] - 48))
        #~ menu2.Destroy()
        menuMain.Destroy()
    

    def OnMenu(self, event, descript, dataset):
        whichdata = dataset
        whichplot = -1
        for i in range(0, len(self.parent.sequenceplotters)):
            if self == self.parent.sequenceplotters[i]:
                whichplot = i
        if descript == 'Play Sequence':
            self.PlayPlot()
        if descript == 'Trace Sequence':
            self.TracePlot()
        if descript == 'Clear Filter':
            if whichdata == 0:
                self.parent.parent.splineCollection_seqfilter = []
            elif whichdata == 1:
                self.parent.parent.splineReferences_seqfilter = []
        if descript == 'Add Parameter Plot':
            self.parent.AddSequencePlotter()
            self.parent.mgr.Update()
        elif descript == 'Remove Parameter Plot':
            self.parent.RemoveSequencePlotter(whichplot)
            self.parent.mgr.Update()
        else:
            jAngles = self.parent.parent.Filters.jointAngleCollection
            for i in range(0, len(jAngles)):
                verhaal = jAngles[i]['description']
                verhaal = verhaal.replace('\n', ' ')
                if verhaal == descript:
                    self.parent.UpdateSequencePlot(i, whichplot, whichdata)
        self.parent.UpdateSequencePlotOverlays()
        
    def DefineLookupTable(self):
        whitening = 0.7
        self.dynamic_generic = vtk.vtkLookupTable()
        self.dynamic_generic.SetNumberOfColors(4)
        self.dynamic_generic.SetRange(0, 4)
        self.dynamic_generic.SetTableValue( 0, (whitening, whitening, whitening ,0.0)) 
        self.dynamic_generic.SetTableValue( 1, (0.0, 0.0, 0.0 ,0.7)) 
        self.dynamic_generic.SetTableValue( 2, (1.0, 1.0, 1.0 ,1.0)) 
        self.dynamic_generic.SetTableValue( 3, (whitening, whitening, whitening ,1.0)) 
        self.dynamic_generic.Build()
        
    def ShowOverlay(self):
        try:
            self.ren.RemoveActor(self.selectionActor)
        except AttributeError:
            pass
        self.canvas = vtk.vtkImageCanvasSource2D()
        self.canvas.SetNumberOfScalarComponents(4)
        self.canvas.SetScalarTypeToUnsignedChar()
        self.canvas.SetExtent(0, self.windowsize[0]-1, 0, self.windowsize[1]-1, 0, 0)        
        self.canvas.SetDrawColor(0,0,0)
        self.canvas.FillBox(0, self.windowsize[0], 0, 50)        
        

        self.canvas.SetDrawColor(1,0,0)
        
        #~ print "self.whichdata: ", self.whichdata
        if self.whichdata == 0:
            sortedlist = self.parent.parent.splineCollection_seqfilter[:]
        elif self.whichdata == 1:
            sortedlist = self.parent.parent.splineReferences_seqfilter[:]
        sortedlist.sort()
        for i in range(0, len(sortedlist)/2):
            self.canvas.FillBox(sortedlist[i*2], sortedlist[i*2+1], 0, 50)
        
        self.canvas.SetDrawColor(2,0,0)
        if self.cursor > -1:            
            self.canvas.FillBox(self.cursor, self.cursor+1, 0, 50)
        
        imagemaptocolors = vtk.vtkImageMapToColors()
        imagemaptocolors.SetOutputFormatToRGBA ()
        imagemaptocolors.SetLookupTable(self.dynamic_generic)
        imagemaptocolors.SetInput(self.canvas.GetOutput())
        
        bbmap = vtk.vtkImageMapper()
        bbmap.SetColorWindow(255.5)
        bbmap.SetColorLevel(127.5)
        bbmap.SetInput(imagemaptocolors.GetOutput())
        self.selectionActor = vtk.vtkActor2D()
        self.selectionActor.SetMapper(bbmap)
        self.ren.AddActor(self.selectionActor)
        self.renWin.Render()
        
        
    def PlotSelected(self, event):
        try:
            self.iren.RemoveObserver(self.lbpf)
            self.iren.RemoveObserver(self.lbpg)
        except AttributeError:
            pass
        x, y = self.iren.GetEventPosition()
        
        index =0
        if self.whichdata == 0:
            index = int(float(x)/float(self.windowsize[0]) * \
                                                    len(self.parent.parent.splineCollection))
            act = self.parent.parent.ShowPose(self.parent.parent.splineCollection[index]['blPos'], type = 2)
            self.parent.SetSliders(self.parent.parent.splineCollection[index]['stance'])                        
        else:
            index = int(float(x)/float(self.windowsize[0]) * \
                                                    len(self.parent.parent.splineReferences))
            act = self.parent.parent.ShowPose(self.parent.parent.splineReferences[index]['blPos'], type = 2)
            self.parent.SetSliders(self.parent.parent.splineReferences[index]['stance'])
        self.parent.tracer.ClearTraces(self.whichdata)
        self.parent.tracer.DrawTrace(self.whichdata, index, None)
                                                    
        self.clicktime = time.clock()
        if self.clicktime - self.lastclicktime < 1:
            if self.whichdata == 0:
                sortedlist = self.parent.parent.splineCollection_seqfilter[:]
            else:
                sortedlist = self.parent.parent.splineReferences_seqfilter[:]
            sortedlist.sort()
            for i in range(0, len(sortedlist)):
                try:
                    if x >= sortedlist[i] and\
                        x <= sortedlist[i + 1]:
                        sortedlist.pop(i+1)
                        sortedlist.pop(i)
                        if self.whichdata == 0:
                            self.parent.parent.splineCollection_seqfilter = sortedlist
                        elif self.whichdata == 1:
                            self.parent.parent.splineReferences_seqfilter = sortedlist
                        break
                except IndexError:
                    pass
            self.parent.UpdateSequencePlotOverlays()
            self.UpdateFilters()
        else:
            if self.whichdata == 0:
                if self.parent.parent.splineCollection_seqfilter == []:
                    self.parent.parent.splineCollection_seqfilter.append(0)
                    self.parent.parent.splineCollection_seqfilter.append(x)
                    self.parent.parent.splineCollection_seqfilter.append(x)
                    self.parent.parent.splineCollection_seqfilter.append(self.windowsize[0])
                else:
                    self.parent.parent.splineCollection_seqfilter.append(x)
                    self.parent.parent.splineCollection_seqfilter.append(x)
            elif self.whichdata == 1:
                if self.parent.parent.splineReferences_seqfilter == []:
                    self.parent.parent.splineReferences_seqfilter.append(0)
                    self.parent.parent.splineReferences_seqfilter.append(x)
                    self.parent.parent.splineReferences_seqfilter.append(x)
                    self.parent.parent.splineReferences_seqfilter.append(self.windowsize[0])
                else:
                    self.parent.parent.splineReferences_seqfilter.append(x)
                    self.parent.parent.splineReferences_seqfilter.append(x)
            
            self.lbpf = self.iren.AddObserver("MouseMoveEvent", \
                                                                                self.PlotMove, 2.0)
            self.lbpg = self.iren.AddObserver("LeftButtonReleaseEvent", \
                                                                                self.PlotRelease, 2.0)
            self.parent.editorpanel.button_4.SetValue(True)
            self.parent.OnChangeFilters(None)
        self.lastclicktime = self.clicktime
        
    def PlotMove(self, event, bla):
        x, y = self.iren.GetEventPosition()
        if self.whichdata == 0:
            if len(self.parent.parent.splineCollection_seqfilter)==4:
                self.parent.parent.splineCollection_seqfilter.pop(2)
                self.parent.parent.splineCollection_seqfilter.insert(2, x)
            else:
                self.parent.parent.splineCollection_seqfilter.pop(len(self.parent.parent.splineCollection_seqfilter)-1)
                self.parent.parent.splineCollection_seqfilter.append(x)
        elif self.whichdata == 1:
            if len(self.parent.parent.splineReferences_seqfilter)==4:
                self.parent.parent.splineReferences_seqfilter.pop(2)
                self.parent.parent.splineReferences_seqfilter.insert(2, x)
            else:
                self.parent.parent.splineReferences_seqfilter.pop(len(self.parent.parent.splineReferences_seqfilter)-1)
                self.parent.parent.splineReferences_seqfilter.append(x)
        self.parent.UpdateSequencePlotOverlays()
        
    def PlotRelease(self, event, bla):
        self.iren.RemoveObserver(self.lbpf)
        self.iren.RemoveObserver(self.lbpg)
        if self.whichdata == 0:
            if self.parent.parent.splineCollection_seqfilter[len(self.parent.parent.splineCollection_seqfilter)-1] == self.parent.parent.splineCollection_seqfilter[len(self.parent.parent.splineCollection_seqfilter)-2]:
                self.parent.parent.splineCollection_seqfilter.pop(len(self.parent.parent.splineCollection_seqfilter)-1)
                self.parent.parent.splineCollection_seqfilter.pop(len(self.parent.parent.splineCollection_seqfilter)-1)
        elif self.whichdata == 1:
            if self.parent.parent.splineReferences_seqfilter[len(self.parent.parent.splineReferences_seqfilter)-1] == self.parent.parent.splineReferences_seqfilter[len(self.parent.parent.splineReferences_seqfilter)-2]:
                self.parent.parent.splineReferences_seqfilter.pop(len(self.parent.parent.splineReferences_seqfilter)-1)
                self.parent.parent.splineReferences_seqfilter.pop(len(self.parent.parent.splineReferences_seqfilter)-1)
        self.UpdateFilters()
        
            
    def UpdateFilters(self):
        self.filtervalues = []
        if self.whichdata == 0:
            sortedlist = self.parent.parent.splineCollection_seqfilter[:]
        elif self.whichdata == 1:
            sortedlist = self.parent.parent.splineReferences_seqfilter[:]
        sortedlist.sort()
        if self.whichdata == 0:
            for i in range(0, len(sortedlist)):
                self.filtervalues.append(int(float(sortedlist[i])/float(self.windowsize[0]) * \
                                                    len(self.parent.parent.splineCollection)))
            self.parent.parent.Filters.RestartFiltering()
        else:
            for i in range(0, len(sortedlist)):
                self.filtervalues.append(int(float(sortedlist[i])/float(self.windowsize[0]) * \
                                                    len(self.parent.parent.splineReferences)))
            self.parent.parent.Filters.RestartFilteringReferences()
        
    def ShowPlot(self):
        self.windowsize = self.iren.GetSize()#(1370, 50)
        
        
        # The vtkImageImporter will treat a python string as a void pointer
        importer = vtk.vtkImageImport()
        importer.SetDataScalarTypeToUnsignedChar()
        importer.SetNumberOfScalarComponents(4)

        canvasset = self.CreatePlot()
        canvas = canvasset[0]
        w = canvasset[1]
        h = canvasset[2]

        # This is where we tell the image importer about the mpl image
        #~ extent = (0, w - 1, 0, h - 1, 0, 0)
        extent = (0, w-1, 0, h-1, 0, 0)
        importer.SetWholeExtent(extent)
        importer.SetDataExtent(extent)
        importer.SetImportVoidPointer(canvas.buffer_rgba(0,0), 1)
        importer.Update()
        #~ for i in range(0,256):
            #~ print importer.GetOutput().GetScalarComponentAsFloat (i, i, 0, 0)
            #~ time.sleep(0.1)

        # It's upside-down when loaded, so add a flip filter
        imflip = vtk.vtkImageFlip()
        imflip.SetInput(importer.GetOutput())
        imflip.SetFilteredAxis(1)

        bbmap = vtk.vtkImageMapper()
        bbmap.SetColorWindow(255.5)
        bbmap.SetColorLevel(127.5)
        bbmap.SetInput(imflip.GetOutput())
        bbact = vtk.vtkActor2D()
        bbact.SetMapper(bbmap)
        

        bbact.SetDisplayPosition (int(-0.16*self.windowsize[0]),-6)
        #~ bbact.SetDisplayPosition (-220, -6) ##width = 1348 = -220, #width = 692 = -110
        self.ren.AddActor(bbact)

    def CreatePlot(self):
        # Now create our plot
        fig = Figure()
        fig.frameon = False
        #fig.set_autoscaley_on(False)
        canvas = FigureCanvasAgg(fig)
        ax = fig.add_subplot(111)#, autoscaley_on = True, autoscalex_on = False)
        ax.set_ybound (-2, 2)
        ax.set_xbound (0, len(self.yValues1))
        ax.set_xticklabels('bla', visible=False)
        ax.set_yticklabels('bla', visible=False)
        ax.annotate(self.label, xy=(24, 24),  xycoords='axes pixels',
                horizontalalignment='left', verticalalignment='center',
                fontsize=20, color=(0.0, 0.0, 0.0))
        ax.annotate(self.label, xy=(25, 25),  xycoords='axes pixels',
                horizontalalignment='left', verticalalignment='center',
                fontsize=20, color=(1.0, 1.0, 1.0))
        rect = ax.patch  # a Rectangle instance
        rect.set_facecolor((0.3, 0.3, 0.3))


        pointsx = matplotlib.numpy.arange(0, len(self.yValues1)).tolist()
        pointsy = self.yValues1#.tolist()
        pointsx.insert(0, 0.0)
        pointsy.insert(0, 0.0)
        pointsx.append(0.0)
        pointsy.append(0.0)
        
        
        #~ ax.bar(pointsx, pointsy, color=self.plotcolor) #color= self.plotcolor, 
        ax.fill(pointsx, pointsy, edgecolor=(1.0, 1.0, 1.0),\
                    facecolor= self.plotcolor, antialiased=True)
        ax.set_xbound (0, len(self.yValues1))
        
        # Powers of 2 image to be clean
        #w,h = 1024, 1024
        w,h = int(self.windowsize[0] * 1.29), int(self.windowsize[1] * 1.3)
        dpi = canvas.figure.get_dpi()
        fig.set_size_inches(1.0*w / dpi, 1.0*h / dpi)
        
        canvas.draw() # force a draw
        return [canvas, w, h]
        
    def PlayPlot(self):
        for i in range(0, (len(self.filtervalues)/2) -1):
            for j in range(self.filtervalues[i*2+1], self.filtervalues[i*2+2]):
                
                if self.whichdata == 0:
                    self.cursor = int(float(j) / len(self.parent.parent.splineCollection)\
                                    * (self.windowsize[0]))
                    self.ShowOverlay()
                    
                    self.parent.parent.ShowPose(self.\
                        parent.parent.splineCollection[j]['blPos'], type = 2)
                elif self.whichdata == 1:
                    self.cursor = int(float(j) / len(self.parent.parent.splineReferences)\
                                    * (self.windowsize[0]))
                    self.ShowOverlay()
                    
                    self.parent.parent.ShowPose(self.\
                        parent.parent.splineReferences[j]['blPos'], type = 2)
                #~ self.parent.tracer.ClearTraces(self.whichdata)
                #~ self.parent.tracer.DrawTrace(self.whichdata, j, None)
                time.sleep(0.01)
                self.parent.Render()
        self.cursor = -1
        self.ShowOverlay()
        
    def TracePlot(self):
        self.parent.tracer.ClearTraces(self.whichdata)
        for i in range(0, (len(self.filtervalues)/2) -1):
            difference = self.filtervalues[i*2+1] - self.filtervalues[i*2+2]
            self.parent.tracer.DrawTrace(self.whichdata, self.filtervalues[i*2+2], [difference, 0])

class MyApp(wx.App):
    def OnInit(self):
        plotsie = Plotter(None, None)        
        plotsie.Show()
        self.SetTopWindow(frame)
        return 1

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()